#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

sem_t empty;
sem_t full;

// 厨师这个线程通过这个函数，不断的往食物窗口放置菜
void produce(int chef_id) {
	// 这里会判断窗口是否为空，如果不为空则等待
	sem_wait(&empty);
	
	// 临界区
	printf("chef %d add food to food window\n", chef_id);
	fflush(stdout);

	// 厨师将菜放入窗口，则通知服务员来取菜
	sem_post(&full);
}

// 服务员这个线程通过这个函数，不断的从食物窗口中取菜
void consume(int waiter_id) {
	// 这里服务员判断窗口是否满的，如果不满，也就是没有食物，则等待
	sem_wait(&full);

	// 临界区
	printf("waiter %d remove food from food window\n", waiter_id);
	fflush(stdout);

	// 当服务员拿完菜，则通知厨师往窗口中放菜
	sem_post(&empty);
}

void *chef_thread(void *args) {
	int chef_id = *((int *)args);
	while (1) {
		// 模拟做菜
		sleep(rand() % 5);
		produce(chef_id);
	}
}

void *waiter_thread(void *args) {
	int waiter_id = *((int *)args);
	while (1) {
		sleep(rand() % 3);
		consume(waiter_id);
	}
}

int main() {
	// 有两个食物窗口
	sem_init(&empty, 0, 2);
	// 一开始食物窗口中没有任何菜，所以这里初始化为 0
	sem_init(&full, 0, 0);

	
	pthread_t chefs[3];
	pthread_t waiters[2];
	int i;
	// 3 个厨师	
	for (i = 0; i < 3; i++) {
		pthread_create(&chefs[i], NULL, chef_thread, &i);
	}
	// 2 个服务员
	for (i = 0; i < 2; i++) {
		pthread_create(&waiters[i], NULL, waiter_thread, &i);
	}
		
	sleep(30);

	sem_destroy(&empty);
	sem_destroy(&full);
	
	return 1;
}
